Fix updating git sources a new lockfile is committed
authorAlex Crichton <alex@alexcrichton.com>
Sun, 10 Aug 2014 05:53:25 +0000 (22:53 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Mon, 11 Aug 2014 03:50:33 +0000 (20:50 -0700)
This is the actual fix for #345

src/cargo/sources/git/utils.rs
tests/test_cargo_compile_git_deps.rs

index 8ef1c9a3e6f0b549d89001c6365adff8fd8907f0..5a42d46f0f5098ba14e1ae72b423b475156c0d4a 100644 (file)
@@ -152,6 +152,10 @@ impl GitRemote {
 
     pub fn rev_for<S: Str>(&self, path: &Path, reference: S)
                            -> CargoResult<GitRevision> {
+        // Make sure we only rev-parse a success if the reference is actually
+        // an object in the git database. Git will otherwise just verify that
+        // it's a 40-length hex string (almost always true)
+        let reference = format!("{}^{{object}}", reference.as_slice());
         Ok(GitRevision(git_output!(*path, "rev-parse", reference.as_slice())))
     }
 
index fc391bc9aa2a0aa4a02c0c38a4cf47d7876c56e5..107c6aa05de4cff4eb2de5b8360224ec466499d7 100644 (file)
@@ -783,3 +783,72 @@ test!(two_deps_only_update_one {
                              UPDATING, git1.url()))
         .with_stderr(""));
 })
+
+test!(stale_cached_version {
+    let bar = git_repo("meta-dep", |project| {
+        project.file("Cargo.toml", r#"
+            [package]
+            name = "bar"
+            version = "0.0.0"
+            authors = []
+        "#)
+        .file("src/lib.rs", "pub fn bar() -> int { 1 }")
+    }).assert();
+
+    // Update the git database in the cache with the current state of the git
+    // repo
+    let foo = project("foo")
+        .file("Cargo.toml", format!(r#"
+            [project]
+            name = "foo"
+            version = "0.0.0"
+            authors = []
+
+            [dependencies.bar]
+            git = '{}'
+        "#, bar.url()))
+        .file("src/main.rs", r#"
+            extern crate bar;
+
+            fn main() { assert_eq!(bar::bar(), 1) }
+        "#);
+
+    assert_that(foo.cargo_process("cargo-build"), execs().with_status(0));
+    assert_that(foo.process(foo.bin("foo")), execs().with_status(0));
+
+    // Update the repo, and simulate someone else updating the lockfile and then
+    // us pulling it down.
+    File::create(&bar.root().join("src/lib.rs")).write_str(r#"
+        pub fn bar() -> int { 1 + 0 }
+    "#).assert();
+    bar.process("git").args(["add", "."]).exec_with_output().assert();
+    bar.process("git").args(["commit", "-m", "test"]).exec_with_output()
+       .assert();
+    let rev = bar.process("git").args(["rev-parse", "HEAD"])
+                 .exec_with_output().assert();
+    let rev = String::from_utf8(rev.output).unwrap();
+
+    File::create(&foo.root().join("Cargo.lock")).write_str(format!(r#"
+        [root]
+        name = "foo"
+        version = "0.0.0"
+        dependencies = [
+         'bar 0.0.0 (git+{url}#{hash})'
+        ]
+
+        [[package]]
+        name = "bar"
+        version = "0.0.0"
+        source = 'git+{url}#{hash}'
+    "#, url = bar.url(), hash = rev).as_slice()).assert();
+
+    // Now build!
+    assert_that(foo.process(cargo_dir().join("cargo-build")),
+                execs().with_status(0)
+                       .with_stdout(format!("\
+{updating} git repository `{bar}`
+{compiling} bar v0.0.0 ({bar}#[..])
+{compiling} foo v0.0.0 ({foo})
+", updating = UPDATING, compiling = COMPILING, bar = bar.url(), foo = foo.url())));
+    assert_that(foo.process(foo.bin("foo")), execs().with_status(0));
+})